/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "sle_seek_service.h"
#include "sle_seek_hal.h"
#include "sle_hilog.h"

namespace OHOS {
namespace NearLink {
namespace SleStandard {

class SleSeekService::SleSeekServiceCallback {
public:
    SleSeekServiceCallback() = default;
    ~SleSeekServiceCallback() = default;

    static void OnSeekStartResult(SleHalErrorCode errCode);
    static void OnSeekStopResult(SleHalErrorCode errCode);
    static void OnSeekResult(const SleSeekResult *result);
    static SleSeekHalCallbacks *BuildHalSeekCallback();

private:
    static SleSeekHalCallbacks halCallback_;
};

void SleSeekService::SleSeekServiceCallback::OnSeekStartResult(SleHalErrorCode errCode)
{
    auto seekService = SleSeekService::GetInstance();
    SLE_ASSERT_AND_RETURN_LOG(seekService, "seek service instance null error!");
    SLE_ASSERT_AND_RETURN_LOG(seekService->callback_, "seek service callback null error!");
    SleSeekState state = (errCode == SLE_HAL_SUCCESS) ? SLE_SEEK_ENABLED_STATE : SLE_SEEK_ERROR_STATE;
    seekService->callback_->OnSeekStateChange(state);
}

void SleSeekService::SleSeekServiceCallback::OnSeekStopResult(SleHalErrorCode errCode)
{
    auto seekService = SleSeekService::GetInstance();
    SLE_ASSERT_AND_RETURN_LOG(seekService, "seek service instance null error!");
    SLE_ASSERT_AND_RETURN_LOG(seekService->callback_, "seek service callback null error!");
    SleSeekState state = (errCode == SLE_HAL_SUCCESS) ? SLE_SEEK_DISABLED_STATE : SLE_SEEK_ERROR_STATE;
    seekService->callback_->OnSeekStateChange(state);
}

void SleSeekService::SleSeekServiceCallback::OnSeekResult(const SleSeekResult *result)
{
    auto seekService = SleSeekService::GetInstance();
    SLE_ASSERT_AND_RETURN_LOG(seekService, "seek service instance null error!");
    SLE_ASSERT_AND_RETURN_LOG(seekService->callback_, "seek service callback null error!");
    seekService->callback_->OnSeekResult(*result);
}

SleSeekHalCallbacks SleSeekService::SleSeekServiceCallback::halCallback_;
SleSeekHalCallbacks *SleSeekService::SleSeekServiceCallback::BuildHalSeekCallback()
{
    halCallback_.OnSeekHalEnableSeekCb = OnSeekStartResult;
    halCallback_.OnSeekHalDisableSeekCb = OnSeekStopResult;
    halCallback_.OnSeekHalSeekResultCb = OnSeekResult;
    return &halCallback_;
}

SleSeekService::SleSeekService()
{
    SLE_LOGD("SleSeekService In");
    SleHalErrorCode ret = InitSleSeekHal();
    SLE_ASSERT_AND_RETURN_LOG(ret == SLE_HAL_SUCCESS, "init sle seek hal failed!");
    serviceCallback_ = std::make_unique<SleSeekServiceCallback>();
    SLE_ASSERT_AND_RETURN_LOG(serviceCallback_, "create service callback ptr failed!");
    ret = SleSeekHalRegisterCallback(serviceCallback_->BuildHalSeekCallback());
    SLE_ASSERT_AND_RETURN_LOG(ret == SLE_HAL_SUCCESS, "register hal seek callback failed!");
}

SleSeekService::~SleSeekService()
{
    SLE_LOGD("~SleSeekService In");
    SleHalErrorCode ret = DeinitSleSeekHal();
    SLE_ASSERT_AND_RETURN_LOG(ret == SLE_HAL_SUCCESS, "deinit sle seek hal failed!");
    serviceCallback_ = nullptr;
}

SleSeekService *SleSeekService::GetInstance()
{
    static SleSeekService instance;
    return &instance;
}

SleErrorCode SleSeekService::StartSeek(SeekParam &param)
{
    SLE_LOGD("StartSeek In");
    SleSeekParam params;
    param.ConvertToSleSeekParam(params);
    SleHalErrorCode ret = SleSeekHalSetSeekParam(&params);
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, SLE_ERR_FAILED, "set seek param failed!");

    ret = SleSeekHalStartSeek();
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, SLE_ERR_FAILED, "start seek failed!");
    return SLE_NO_ERROR;
}

SleErrorCode SleSeekService::StopSeek()
{
    SleHalErrorCode ret = SleSeekHalStopSeek();
    SLE_ASSERT_AND_RETURN_RET_LOG(ret == SLE_HAL_SUCCESS, SLE_ERR_FAILED, "stop seek failed!");
    return SLE_NO_ERROR;
}

SleErrorCode SleSeekService::RegisterSeekCallback(ISeekCallback &callback)
{
    SLE_LOGD("RegisterSeekCallback In");
    SLE_ASSERT_AND_RETURN_RET_LOG(callback_ != &callback, SLE_ERR_INVALID_PARAM, "callback already registered error!");
    callback_ = &callback;
    return SLE_NO_ERROR;
}

SleErrorCode SleSeekService::UnregisterSeekCallback(ISeekCallback &callback)
{
    SLE_LOGD("UnregisterSeekCallback In");
    SLE_ASSERT_AND_RETURN_RET_LOG(callback_ == &callback, SLE_ERR_INVALID_PARAM, "callback already unregistered error!");
    callback_ = nullptr;
    return SLE_NO_ERROR;
}
} // SleStandard
} // NearLink
} // OHOS